fun strlen(str: Char[]): Int {
    var i = 0;
    while (str[i] != 0) ++i;
    i
}

fun strcmp(s1: Char[], s2: Char[]): Int {
    val len = strlen(s1);
    var i = 0;
    while (s1[i] == s2[i] && i<len) ++i;
    if (s1[i] < s2[i]) -1
    else if (s1[i] == s2[i]) 0
    else 1
}

fun strcpy(dest: Char[], src: Char[]) {
    val len = strlen(src);
    for (var i=0; i<len; ++i)
        dest[i] = src[i];
    dest[len] = '\0'
}

fun strcpy_range(dest: Char[], src: Char[], l: Int, r: Int) {
    // printf("strcpy_range: copying %s\n", src);
    val len = r-l;
    for (var i=0; i<len; ++i)
        dest[i] = src[l+i];
    dest[len] = '\0'
}

fun strToInt(str: Char[]): Int {
    var ret = 0;
    for (var i=0; '0' <= str[i] && str[i] <= '9'; ++i)
        ret = ret * 10 + (str[i] - '0');
    ret
}

fun strNextChar(str: Char[], start: Int, aim: Char): Int {
    var i=start;
    // printf("starting at %d\n", i);
    while (str[i]!='\0' && str[i]!=aim) {
        ++i;
        // printf("now i = %d\n", i);
    }
    if (str[i]==aim) i
    else -1
}

fun findOrInsert(table: Char[][100], length: Int&, name: Char[]): Int {
    for (var i=length-1; i>=0; --i)
        if (strcmp(table[i], name) == 0) {
            return i;
        }
    // 没找到，新建一个
    strcpy(table[length], name);
    ++length;
    length-1
}

fun find(table: Char[][100], length: Int, name: Char[]): Int {
    for (var i=length-1; i>=0; --i)
        if (strcmp(table[i], name) == 0) {
            return i;
        }
    -1;
}


fun nextCursor(input: Char[], cur: Int): Int {
    var ret = cur;
    while (input[ret] != '|') ++ret;
    ret
}

fun processRequire(str: Char[], require: Char[][7][100], classCount: Int&, requireCount: Int[]) {
    classCount = 0;
    if (str[0] != 0) {
        var len = strlen(str);
        str[len] = ';';
        str[len+1] = '\0';
        ++len;
        // printf("processing Require: %s\n", str);
        var cur = 0;
        var nextSemi: Int;
        requireCount[0] = 0;
        while ((nextSemi=strNextChar(str, cur, ';')) != -1) {
            // printf("nextSemi at %d\n", nextSemi);
            // 找到分号
            // 一组下逐个课程
            while (true) {
                var sectionIdx = requireCount[classCount]; // 分组下课程idx
                var nextComma = cur;
                while (str[nextComma] != ',' && nextComma != nextSemi) ++nextComma;
                // printf("nextComma at %d\n", nextComma);
                strcpy_range(require[classCount][sectionIdx], str, cur, nextComma);
                cur = nextComma + 1;
                requireCount[classCount] = sectionIdx + 1;
                if (nextComma == nextSemi) break;
            }
            ++classCount;
        }
    }
}

fun main(): Int {
    var nameTable: Char[103][100];
    var nameCount = 0;
    var credit: Int[103];
    var requireClassCount: Int[103];
    var requireCount: Int[103][7];
    var require: Char[103][7][7][100];
    var grade: Int[103];
    var input: Char[200];
    var inputLen: Int;
    var isPossiable: Bool[103];

    for (gets(input); (inputLen=strlen(input))!=0; gets(input)) {
        // 课程名称
        var cur = 0;
        var nextCur = nextCursor(input, 0);
        var tmpStr: Char[500];
        var tmpStr2: Char[500];
        strcpy_range(tmpStr, input, cur, nextCur);
        var idx = findOrInsert(nameTable, nameCount, tmpStr);
        
        // 学分
        cur = nextCur + 1;
        nextCur = nextCursor(input, cur);
        strcpy_range(tmpStr, input, cur, nextCur);
        credit[idx] = strToInt(tmpStr);

        // 前置课程
        cur = nextCur + 1;
        nextCur = nextCursor(input, cur);
        strcpy_range(tmpStr, input, cur, nextCur);
        processRequire(tmpStr, require[idx], requireClassCount[idx], requireCount[idx]);

        // 成绩
        cur = nextCur + 1;
        if (cur == inputLen) {
            grade[idx] = -1;
            // printf("NO GRADE: %d=%d\n", grade[idx], -1)
        }
        else {
            val g = input[cur];
            grade[idx] = 
                if (g == 'A') 4;
                else if (g == 'B') 3;
                else if (g == 'C') 2;
                else if (g == 'D') 1;
                else 0;
            // printf("grade found: %c\n", grade[idx]);
        }
    }

    // 打印解析后的表格
    /* 
    for (var i=0; i<nameCount; ++i) {
        printf("%s|%d|", nameTable[i], credit[i]);
        for (var j=0; j<requireClassCount[i]; ++j) {
            for (var k=0; k<requireCount[i][j]; ++k)
                printf("%s,", require[i][j][k]);
            printf(";");
        }
        printf("|%d\n", grade[i]);
    }
    */

    // 计算学分
    var attempted = 0;
    var completed = 0;
    var remaining = 0;
    var GP = 0;
    for (var i=0; i<nameCount; ++i) {
        if (grade[i] >= 0) {
            attempted = attempted + credit[i];
            GP = GP + grade[i] * credit[i];
        }
        if (grade[i] > 0)
            completed = completed + credit[i];
        if (grade[i] <= 0)
            remaining = remaining + credit[i];
        
        // 判断是否推荐
        // printf("\nchecking %s\n", nameTable[i]);
        isPossiable[i] = requireClassCount[i] == 0 && grade[i] <= 0;
        if (grade[i] <= 0) {
            for (var j=0; j<requireClassCount[i] && isPossiable[i]==false; ++j) {
                var k=0;
                var ok = true;
                while (ok && k < requireCount[i][j]) {
                    var rId = find(nameTable, nameCount, require[i][j][k]);
                    if (rId == -1) {
                        ok = false;
                        // printf("failed for rId=-1: %s\n", require[i][j][k]);
                    } else {
                        if (grade[rId] <= 0)
                            ok = false;
                        // printf("failed for grade[rId]<=0: %s\n", require[i][j][k]);
                    }
                    ++k;
                }
                if (ok) isPossiable[i] = true;
            }
        }
    }

    var GPA = 0.0;
    if (attempted > 0) {
        // printf("GP=%d  attempted=%d\n", GP, attempted);
        GPA = 1.0 * GP / attempted;
    }

    printf("GPA: %.1f\n", GPA);
    printf("Hours Attempted: %d\n", attempted);
    printf("Hours Completed: %d\n", completed);
    printf("Credits Remaining: %d\n\n", remaining);
    printf("Possible Courses to Take Next\n");
    var allCompleted = true;
    for (var i=0; i<nameCount; ++i) {
        if (grade[i] <= 0) allCompleted = false;
        if (isPossiable[i])
            printf("  %s\n", nameTable[i]);
    }

    if (allCompleted)
        printf("  None - Congratulations!\n");

    0
}